package GA;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.io.InputStreamReader;

import Operations.Operation;
import Operations.CreateObject;
import Operations.ValuesGenerator;
import random.TestClusterBuilder;
import util.*;
import crossover.*;
import mutation.*;
public class ChromosomeFormer {

    public static Chromosome buildNewChromosome(TestClusterBuilder TestCluster) {
    	Map<String, List<CreateObject>> constructors= new LinkedHashMap <String, List<CreateObject>> ();
    	List<Operation> ops = new LinkedList<Operation>();
    	constructors=CreateObject.generateInitialClass(TestCluster);
		for (int i = 0; i < GAConfig.TestCaseSize; i++)
			ops.add(Operation.randomlyGenerate(TestCluster));
		Chromosome chrom = new Chromosome(TestCluster.getCluster(),TestCluster.getRefFactory(),constructors, ops);
		return chrom;
    }
 
	public static void main(String[] args) {
		try {
			 GAInfo     gaInfo=  new GAInfo();
				ValuesGenerator.resetSeed(10);
				
			Crossover crossoverStrategy = GAOperationsConfig.getCrossoverStrategy();
			Mutation ChangeValueStrategy = GAOperationsConfig.getMutationChangeValueStrategy();
			Mutation MethodInsertStrategy = GAOperationsConfig.getMutationMethodInsertStrategy();
			Mutation MethodDeleteStrategy = GAOperationsConfig.getMutationMethodDeleteStrategy();

			System.out.println("CUT is:" + GAConfig.classFilePath);
			 Set<Class<?>> allClasses = new LinkedHashSet<Class<?>>();
		      //get class from file
		      allClasses.addAll(TestClusterBuilder.readClassFromFile());

		      System.out.println("There are " + allClasses.size() + " classes as input");
		      
		      System.out.println(allClasses);
		      Set<Class<?>> classesToTest = TestClusterBuilder.filterUntestableClasses(allClasses);
		      System.out.println("There are " + classesToTest.size() + " classes to test after filtering");
		      System.out.println(classesToTest);

			// calculate the test cluster and the set of types involved in the
				TestClusterBuilder TestCluster = new TestClusterBuilder(classesToTest);		
				gaInfo.setTestCluster(TestCluster);
			Chromosome chrom1=buildNewChromosome(TestCluster);
			System.out.println(chrom1.toString());
		//execute the chiromosme;

			
			String input;
			BufferedReader in = new BufferedReader(new InputStreamReader(
					System.in));

			Chromosome chrom2 = buildNewChromosome(TestCluster);
			while ((input = in.readLine()) != null) {
				//ReflectionExecutor.execute(chrom1);
				int randCohice=ValuesGenerator.getRandomIntBetween(0, 3);
			//	randCohice=1;
				if (randCohice == 0) {
					System.out.println("Insert Random Method "
							+ MethodInsertStrategy.getClass().getName());
					MethodInsertStrategy.setExtraInfo(gaInfo);
					chrom1=MethodInsertStrategy.mutateChromosome(chrom1.clone());
					System.out.println("chrom1: " + chrom1);
				}
				else if (randCohice == 1) {
					System.out.println("Input value changed.");
					ChangeValueStrategy.setExtraInfo(gaInfo);
					chrom1=ChangeValueStrategy.mutateChromosome(chrom1.clone());
					System.out.println("chrom1: " + chrom1);
				}
				else if (randCohice == 2){
					System.out.println("Delete Random Method "
							+ MethodDeleteStrategy.getClass().getName());
					MethodDeleteStrategy.setExtraInfo(gaInfo);
					chrom1=MethodDeleteStrategy.mutateChromosome(chrom1.clone());
					System.out.println("chrom1: " + chrom1);
				
				}
				else if (randCohice == 3){
					System.out.println("Crossover Strategy: "
							+ crossoverStrategy.getClass().getName());
					Chromosome[] offspring = crossoverStrategy.crossOver(
							chrom1, chrom2);
					System.out.println("offspring1:" + offspring[0].getSize());
					System.out.println("\noffspring2:" + offspring[1].getSize());
					chrom1= offspring[0].clone();
					System.out.println("\nchrom1:" + chrom1.getSize());
					chrom2= offspring[1].clone();
					System.out.println("\nchrom2:" + chrom2.getSize());

				}
			}

			System.exit(0);
		} catch (Throwable e) {
			System.err.println("chromFormer.main: " + e.getMessage());
	//		System.exit(1);
		}

		}
}
